using System;
using System.Collections.Generic;
using System.IO;
using Common;
using Common.NotifyEvent;

namespace SProject.Rule
{
	[Serializable]
	public abstract class Rule : NotifyPropertyChanged
	{
		private bool _IsReadOnly;

		private bool _BasicRule = true;

		private string _DllPath;

		private string _Version = "";

		private byte[] _Data;

		private byte[] _AdvRuleNote;

		public bool IsReadOnly
		{
			get
			{
				return _IsReadOnly;
			}
			set
			{
				if (_IsReadOnly != value)
				{
					_IsReadOnly = value;
					OnPropertyChanged("IsReadOnly");
				}
			}
		}

		public bool BasicRule
		{
			get
			{
				return _BasicRule;
			}
			set
			{
				if (_BasicRule != value)
				{
					_BasicRule = value;
					OnPropertyChanged("BasicRule");
				}
			}
		}

		public string DllPath
		{
			get
			{
				return _DllPath;
			}
			set
			{
				_DllPath = value;
				OnPropertyChanged("DllPath");
			}
		}

		public string Version
		{
			get
			{
				return _Version;
			}
			set
			{
				if (!(_Version == value))
				{
					_Version = value;
					OnPropertyChanged("Version");
				}
			}
		}

		public byte[] Data
		{
			get
			{
				return _Data;
			}
			set
			{
				if (_Data != value)
				{
					_Data = value;
					OnPropertyChanged("Data");
				}
			}
		}

		public byte[] AdvRuleNote
		{
			get
			{
				return _AdvRuleNote;
			}
			set
			{
				if (_AdvRuleNote != value)
				{
					_AdvRuleNote = value;
					OnPropertyChanged("AdvRuleNote");
				}
			}
		}

		public Rule()
		{
		}

		public abstract Rule CreateRule();

		public virtual void Copy(Rule rule)
		{
			BasicRule = rule.BasicRule;
			DllPath = rule.DllPath;
			if (rule.Data != null)
			{
				Data = new byte[rule.Data.Length];
				rule.Data.CopyTo(Data, 0);
			}
		}

		public virtual Rule Clone()
		{
			Rule rule = CreateRule();
			rule.Copy(this);
			return rule;
		}

		protected virtual void GetData(List<PropertyKey> keys, List<byte[]> datas)
		{
			keys.Add(PropertyKey.Key_BasicRule);
			datas.Add(BytesConverter.GetBytes(BasicRule));
			if (!string.IsNullOrEmpty(DllPath))
			{
				keys.Add(PropertyKey.Key_DllPath);
				datas.Add(BytesConverter.GetBytes(DllPath));
				if (Data != null)
				{
					keys.Add(PropertyKey.Key_DllData);
					datas.Add(Data);
				}
				if (!string.IsNullOrEmpty(Version))
				{
					keys.Add(PropertyKey.Key_Version);
					datas.Add(BytesConverter.GetBytes(Version));
				}
			}
			if (AdvRuleNote != null)
			{
				keys.Add(PropertyKey.Key_AdvRuleNote);
				datas.Add(AdvRuleNote);
			}
			keys.Add(PropertyKey.Key_IsReadOnly);
			datas.Add(BytesConverter.GetBytes(IsReadOnly));
		}

		protected virtual void SetData(List<PropertyKey> keys, List<byte[]> datas)
		{
			for (int i = 0; i < keys.Count; i++)
			{
				SetData(keys[i], datas[i]);
			}
		}

		protected virtual void SetData(PropertyKey key, byte[] data)
		{
			switch (key)
			{
			case PropertyKey.Key_BasicRule:
				BasicRule = BytesConverter.BytesToBool(data);
				break;
			case PropertyKey.Key_DllPath:
				DllPath = BytesConverter.BytesToString(data);
				break;
			case PropertyKey.Key_Version:
				Version = BytesConverter.BytesToString(data);
				break;
			case PropertyKey.Key_DllData:
				_Data = data;
				break;
			case PropertyKey.Key_AdvRuleNote:
				_AdvRuleNote = data;
				break;
			case PropertyKey.Key_IsReadOnly:
				IsReadOnly = BytesConverter.BytesToBool(data);
				break;
			}
		}

		public virtual void SaveToStream(StreamEx stream)
		{
			stream.Write(PropertyKey.Key_ProjectRule);
			List<PropertyKey> keys = new List<PropertyKey>();
			List<byte[]> list = new List<byte[]>();
			GetData(keys, list);
			stream.Write(PropertyKey.Key_Index);
			stream.WriteIndex(keys, list);
			stream.Flush();
		}

		public virtual bool ReadFromStream(StreamEx stream)
		{
			PropertyKey propertyKey = stream.ReadKey();
			if (propertyKey == PropertyKey.Key_ProjectRule)
			{
				propertyKey = stream.ReadKey();
				if (propertyKey == PropertyKey.Key_Index)
				{
					List<PropertyKey> keys;
					List<byte[]> dates;
					stream.ReadIndex(out keys, out dates);
					SetData(keys, dates);
					return true;
				}
				stream.Seek(-4L, SeekOrigin.Current);
				while (true)
				{
					switch (stream.ReadKey())
					{
					case PropertyKey.Key_BasicRule:
						BasicRule = stream.ReadBool();
						break;
					case PropertyKey.Key_DllPath:
						DllPath = stream.ReadString();
						break;
					case PropertyKey.Key_DllData:
					{
						int len = stream.ReadInt();
						_Data = stream.ReadBytes(len);
						break;
					}
					default:
						stream.Seek(-4L, SeekOrigin.Current);
						return true;
					}
				}
			}
			stream.Seek(-4L, SeekOrigin.Current);
			return false;
		}
	}
}
